home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / ccmd / pwcrunch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-08-19  |  3.7 KB  |  163 lines

  1. /*
  2.  * program to create a passwd.crunch file.  This is a passwd table which can
  3.  * be read into memory very quickly.  Note this file is presorted by username.
  4.  * it format is:
  5.  * bytes 1-4: number passwd entries in the passwd file -- written as
  6.  *        write(fd, &int, sizeof(int) -- that is, byteswapped on a vax.
  7.  * n bytes:  passwd entries, with all string pointers as offsets into a single
  8.  *        buffer.  This section will be of size:
  9.  *            (n * sizeof struct passwd)
  10.  *         where n is the number of passwd entries read in above.
  11.  * the rest of the file contains all of the strings from these passwd entries.
  12.  * the address of the buffer this is read into should be added to all of 
  13.  * the pointer fields in each passwd entry.
  14.  */
  15.  
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <sys/file.h>
  19. #include <stdio.h>
  20. #include <pwd.h>
  21.  
  22. #define GROW 100
  23. #define BUFGROW 1000
  24.  
  25. static struct passwd *ents;
  26. static char *buf;
  27. static int howmany = 0;
  28. static int buflen = 0;
  29. static int used = 0;
  30. static max = 0;
  31. char *malloc(), *realloc();
  32.  
  33. main(argc,argv) 
  34. int argc;
  35. char **argv;
  36. {
  37.     char buf[100];
  38.  
  39.     switch(argc) {
  40.     case 1:
  41.     crunchpw("/etc/passwd.crunch");
  42.     break;
  43.     case 2:
  44.     crunchpw(argv[1]);
  45.     break;
  46.     default:
  47.     fprintf(stderr,"usage: crunchpw [crunchfile]");
  48.     break;
  49.     }
  50. }
  51.  
  52. crunchpw(tofile) {
  53.     struct passwd *p;
  54.     struct stat b1, b2;
  55.  
  56.     if (stat("/etc/passwd", &b1) != 0) {
  57.     perror("/etc/passwd");
  58.     exit(1);
  59.     }
  60.     if (stat(tofile, &b2) == 0 && b2.st_mtime > b1.st_mtime)
  61.     exit(0);
  62.     while(p = getpwent())        /* for all entries */
  63.     crunchpwent(p);            /* compact it */
  64.     write_crunchfile(tofile);        /* write out compacted version */
  65. }
  66.  
  67. /*
  68.  * compact a single passwd entry
  69.  */
  70. crunchpwent(p) 
  71. struct passwd *p;
  72. {
  73.     struct passwd *p1;
  74.  
  75.     if (howmany == max)            /* make space if we need it */
  76.     grow_entries();
  77.     p1 = &ents[howmany];
  78.     bcopy(p,p1,sizeof(struct passwd));    /* copy all the data */
  79.     copystr(&p1->pw_name);        /* and then all of the strings */
  80.     copystr(&p1->pw_passwd);        /* but fix the string ptrs as we go */
  81. #ifdef SYSV
  82.     copystr(&p1->pw_age);
  83. #endif
  84.     copystr(&p1->pw_comment);
  85.     copystr(&p1->pw_gecos);
  86.     copystr(&p1->pw_dir);
  87.     copystr(&p1->pw_shell);
  88.     howmany++;
  89. }
  90.  
  91. /*
  92.  * make more space for entries.
  93.  * we want a contiguous table.
  94.  */
  95. grow_entries() {
  96.     max += GROW;
  97.     if (ents == NULL) {
  98.     ents = (struct passwd *) malloc((max)*sizeof(struct passwd));
  99.     }
  100.     else {
  101.     ents = (struct passwd *) realloc(ents,(max)*sizeof(struct passwd));
  102.     }
  103. }
  104.  
  105. /*
  106.  * copy the string into the buffer we are making, and set the string pointer
  107.  * to be the index into that buffer.
  108.  */
  109. copystr(s)
  110. char **s;
  111. {
  112.     if (used + strlen(*s) > buflen) {    /* expand buffer if necessary */
  113.     buflen += BUFGROW;
  114.     if (buf == NULL) buf = malloc(buflen);
  115.     else buf = realloc(buf,buflen);
  116.     }
  117.     strcpy(&buf[used], *s);        /* copy the string */
  118.     *s = (char *) used;            /* set ptr to be the index */
  119.     used += strlen(&buf[used])+1;    /* count the space */
  120. }
  121.  
  122. pwcmp(p1,p2)
  123. register struct passwd *p1,*p2;
  124. {
  125.     register char *b1 = &buf[(int)p1->pw_name], *b2 = &buf[(int)p2->pw_name];
  126.     return(strcmp(b1,b2));
  127. }
  128.  
  129. /*
  130.  * write out the compacted file
  131.  */
  132. write_crunchfile(tofile) {
  133.     int fd;
  134.     fd = open(tofile,O_WRONLY|O_CREAT,0444);
  135.     if (fd == -1) {
  136.     perror(tofile);
  137.     exit(1);
  138.     }
  139.     xwrite(fd,&howmany,sizeof(howmany)); /* write how many entries */
  140.     qsort(ents, howmany, sizeof(struct passwd), pwcmp);
  141.     xwrite(fd,ents,sizeof(struct passwd)*howmany); /* write the entries */
  142.     xwrite(fd,buf,used);        /* write the strings */
  143.     close(fd);
  144. }
  145.  
  146. xwrite(fd,buf,len)
  147. int fd,len;
  148. char *buf;
  149. {
  150.     int sofar = 0,x;
  151.  
  152.     while(sofar < len) {
  153.     x = write(fd, buf+sofar, len - sofar);
  154.     if (x == -1) {
  155.         perror("write");
  156.         return(-1);
  157.     }
  158.     sofar += x;
  159.     }
  160.     return(len);
  161. }
  162.  
  163.